package com.zhf.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.zhf.mapper.UserMapper;
import com.zhf.pojo.EsUser;
import com.zhf.pojo.User;
import com.zhf.service.UserService;
import com.zhf.util.DuanxinUtil;
import com.zhf.util.R;
import com.zhf.vo.UserVo;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 郑海飞
 * @version 1.0
 * @description:
 * @date 2024/3/27 9:32
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public void sendCode(UserVo userVo) {
        //生成随机的验证码
        String code = RandomUtil.randomNumbers(4);
        userVo.setCode(code);
        //发送消息
        rabbitTemplate.convertAndSend("bwie", JSON.toJSONString(userVo));
        //将手机号存入redis中
        stringRedisTemplate.opsForValue().set("CODE" + userVo.getMobile(), code, 1, TimeUnit.MINUTES);
    }

    @Override
    public void save(UserVo userVo) {
        //获取redis中的验证码
        String redisCode = stringRedisTemplate.opsForValue().get("CODE" + userVo.getMobile());
        //比较验证码是否正确
        if(redisCode!=null || redisCode.equals(userVo.getCode())){
            //添加方法
            User user = BeanUtil.toBean(userVo, User.class);
            userMapper.insert(user);
        }else{
            //验证码错误
            System.out.println("验证码错误,添加失败");
        }
    }



    //接收消息
    @RabbitListener(queues = "bwie")
    public void resvmessage(Message message, Channel channel){
        try {
            String msg=new String(message.getBody());
            System.out.println("接受消息"+msg);
            UserVo userVo = JSON.parseObject(msg, UserVo.class);
            User user = JSON.parseObject(msg, User.class);
            if(user!=null){
                userMapper.updateBy(user.getId());
            }
            if(userVo!=null){
                //发送短信
                DuanxinUtil.sendDuanxin(userVo.getMobile(),userVo.getCode());
            }

            //确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    @PostConstruct
    public void init(){
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                String msg=new String(message.getBody());
                System.out.println("消息发送失败"+msg);
                //重新发送消息
                rabbitTemplate.convertAndSend(exchange,msg);
            }
        });
    }

    @Scheduled(cron = "0 0/10 * * * ?")
    public void  time(){
        String time = stringRedisTemplate.opsForValue().get("time");
        Date date = new Date();
        //全量同步
        if(StringUtils.isEmpty(time)){
          List<EsUser> esUserList= userMapper.selectAll(String.valueOf(date));
          esUserList.stream().forEach(esUser -> {
              elasticsearchRestTemplate.save(esUser);
          });
          stringRedisTemplate.opsForValue().set("time",String.valueOf(date.getTime()));
          return;
        }
        //增量同步
        Date current = new Date(Long.valueOf(time));
        List<EsUser> esUserList= userMapper.selectUser(current,date);
        esUserList.stream().forEach(esUser -> {
            elasticsearchRestTemplate.save(esUser);
        });
        stringRedisTemplate.opsForValue().set("time",String.valueOf(date.getTime()));
    }
    @Override
    public R userList(UserVo userVo) {
        //创建布尔查询
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        //判断用户名
        if(StringUtils.isNotEmpty(userVo.getUname())){
            builder.must(QueryBuilders.termQuery("uname",userVo.getUname()));
        }
        //判断手机号
        if(StringUtils.isNotEmpty(userVo.getMobile())){
            builder.must(QueryBuilders.termQuery("mobile", userVo.getMobile()));
        }
        //排序
        Sort sort = Sort.by(Sort.Direction.DESC, "updateTime");
        //分页
        PageRequest of = PageRequest.of(userVo.getPageNum() - 1, userVo.getPageSize(), sort);
        //高亮
        HighlightBuilder.Field uname = new HighlightBuilder.Field("uname")
                .preTags("<font color='red'>")
                .postTags("</font>")
                .requireFieldMatch(false);
        //创建查询对象
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(builder);
        queryBuilder.withPageable(of);
        queryBuilder.withHighlightFields(uname);
        //执行查询
        SearchHits<EsUser> search = elasticsearchRestTemplate.search(queryBuilder.build(), EsUser.class);
        ArrayList<EsUser> list = new ArrayList<>();
        //获取分页条数
        long totalHits = search.getTotalHits();
        //获取总页数
        search.forEach(item ->{
            EsUser content = item.getContent();
            List<String> highlightField = item.getHighlightField("uname");
            if(ObjectUtil.isNotEmpty(highlightField)&&highlightField.size()>0){
                String s = highlightField.get(0);
                content.setUname(s);
            }
            //添加集合
            list.add(content);
        });
        //创建map集合
        HashMap<String, Object> map = new HashMap<>();
        //设置map集合
        map.put("total",totalHits);
        map.put("pageNum",userVo.getPageNum());
        map.put("pageSize",userVo.getPageSize());
        map.put("list",list);
        //返回统一对象
        return R.ok().message("查询成功").data("list",map);

    }

    @Override
    public R update(Integer id) {
        User user = new User();
        user.setId(id);
        rabbitTemplate.convertAndSend("bwie",JSON.toJSONString(user));
        return R.ok().message("消息发送成功");
    }


}
